<template>
  <a-modal v-model:visible="modalVisible" :footer="null" :destroyOnClose="true" width="760px" bodyStyle="padding:0"
    :afterClose="afterClose" :getContainer="getContainer">
    <a-layout class="file-upload">
      <a-layout-sider v-if="online" style="background-color: #f7f7f7">
        <div class="file-upload-add">
          <a-button type="primary" @click="dirVisible = true">
            <template #icon>
              <FolderAddOutlined />
            </template>新增目录
          </a-button>
        </div>
        <a-menu mode="inline" @select="onDirSelect" v-model:selectedKeys="directorySelectedKeys"
          class="file-upload-dire-menu">
          <a-menu-item v-for="item in directory" :key="item.id">
            <component :is="$Icon['FolderFilled']" style="color: #52c41a" />
            <span>{{ item.dirName }}</span>
          </a-menu-item>
        </a-menu>
      </a-layout-sider>
      <a-layout>
        <a-layout-content class="file-upload-content">
          <h4 v-show="tabsActiveKey == 1">上传文件限制大小{{ fileSizeUnit }},数量{{ fileNum }}</h4>
          <h4 v-show="tabsActiveKey == 2">选中文件限制数量{{ fileNum }}/{{ selectedImage }}</h4>
          <a-tabs v-model:activeKey="tabsActiveKey" @change="onTabsChange" :animated="false">
            <a-tab-pane :key="1">
              <template #tab>
                <span>
                  <component :is="$Icon['CloudUploadOutlined']"></component>上传文件
                </span>
              </template>
              <div class="file-upload-file-wap file-upload-upload-wap">
                <div class="file-upload-upload-item" v-for="(item, index) in fileList" :key="index">
                  <img :src="item.src" />
                  <div class="file-upload-upload-item-status" v-show="item.errorCode == 1">
                    <component :is="$Icon['CheckCircleFilled']"></component>
                  </div>
                  <div class="file-upload-upload-item-size">{{ item.size }}</div>
                  <div class="file-upload-upload-item-progress">
                    <a-progress :percent="item.progress" :showInfo="false" size="small" strokeLinecap="square"
                      :strokeWidth="5" />
                  </div>
                  <div class="file-upload-upload-item-name" :title="item.name">{{ item.name }}</div>
                </div>
              </div>
            </a-tab-pane>
            <a-tab-pane :key="2" v-if="online">
              <template #tab>
                <span>
                  <component :is="$Icon['CloudServerOutlined']"></component>图片管理
                </span>
              </template>
              <div class="file-upload-file-wap">
                <ul class="file-upload-online-list">
                  <li v-for="(item, index) in onlineImgs" :key="index" @click="onImageSelected(index, item.url)">
                    <img :src="item.url" />
                    <span class="file-upload-online-list-img-selected" v-show="item.selected">
                      <component :is="$Icon['CheckCircleFilled']"></component>
                    </span>
                  </li>
                </ul>
                <div class="file-upload-online-btn">
                  <a-button type="dashed" size="mini" block :disabled="nextMarker == null" @click="onLoadMoreFile">
                    {{
                        nextMarker == null ? "没有更多了" : "加载更多"
                    }}
                  </a-button>
                </div>
              </div>
            </a-tab-pane>
          </a-tabs>
        </a-layout-content>
        <a-layout-footer class="file-upload-footer">
          <button class="ant-btn ant-btn-primary upload-btn" ref="domUploaderBtn" v-show="tabsActiveKey == 1">
            <component :is="$Icon['CloudUploadOutlined']"></component>
            <span>上传文件</span>
          </button>
          <a-button type="primary" v-show="tabsActiveKey == 2" @click="onSelected">确定选择</a-button>
          <a-button @click="onCancel">取消</a-button>
        </a-layout-footer>
      </a-layout>
    </a-layout>
  </a-modal>

  <a-modal v-model:visible="dirVisible" title="添加文件目录" @ok="onAddDirSubmit">
    <a-textarea v-model:value="dirName" placeholder="输入目录名称,不能超过10个字符" showCount :maxlength="10" />
  </a-modal>
</template>

<script lang="ts" setup>

import { ref, defineProps, withDefaults, defineEmits, watch } from 'vue';
import { message } from "ant-design-vue";
import { FileManageService } from '@/services/FileManage/FileManageService';
import { UserContext } from '@/utils/UserContext';
import appsettings from '@/appsettings';

/**组件参数*/
export interface IProps {
  /** 文件数量 选中跟上传合并使用*/
  fileNum: number;
  /** 文件大小 默认300KB 单位/b */
  fileSize?: number;

  /**限制文件类型*/
  accept?: any;
  /**
   * 打开状态
   */
  opend: boolean;

  //挂在的容器节点
  getContainer: HTMLElement;

  //是否开启在线管理
  online?: boolean;

  /**
   * 成功回调
   */
  onSuccess?: Function;

  /**
   * 结束回调
   */
  onEnd?: Function

}

const props = withDefaults(defineProps<IProps>(), {
  fileNum: 1,
  fileSize: 300 * 1024,
  opend: true,
  online: true,
  accept: {
    title: "Images",
    extensions: "gif,jpg,jpeg,bmp,png",
    mimeTypes: "image/*"
  }
})

const emits = defineEmits(["update:modelValue"]);

const dirVisible = ref(false);
const dirName = ref("");
const directory = ref<any[]>([]);
const fileList = ref<any[]>([]); //上传文件列表
const uploadServerUrl = appsettings.UploadURL;
const modalVisible = ref(props.opend);
//dom
const domUploaderBtn = ref(null);
let _uploader: any = null;


//监听
watch(domUploaderBtn, (next, prev) => {
  if (next) {
    createWebUploader();
  }
});

const fileSizeUnit = ref("");
const fileUnit = () => {
  fileSizeUnit.value = WebUploader.Base.formatSize(props.fileSize, 0, [
    "B",
    "KB",
    "MB",
  ]);
};

fileUnit();

let createWebUploader = () => {
  if (_uploader != null) {
    return;
  }
  //上传
  _uploader = WebUploader.create({
    server: uploadServerUrl,
    pick: domUploaderBtn.value,
    formData: { tenantId: UserContext.getId() },
    compress: false, //不压缩
    fileNumLimit: props.fileNum, // 验证文件总数量, 超出则不允许加入队列。
    fileSingleSizeLimit: props.fileSize, // 验证单个文件大小是否超出限制, 超出则不允许加入队列
    accept: props.accept
  });
  //当文件添加到上传队列后触发
  _uploader.on("filesQueued", function (files: any) {
    files.forEach((file: any) => {
      var size = WebUploader.Base.formatSize(file.size, 0, [
        "B",
        "KB",
        "MB",
      ]);
      // 创建缩略图 errorCode 0=初始化 1=错误 2=上传成功
      _uploader.makeThumb(
        file,
        function (error: any, src: any) {
          if (error) {
            fileList.value.push({
              id: file.id,
              src: "",
              name: file.name,
              size: size,
              progress: file.processed,
              errorCode: 0,
              errorMsg: "",
            });
            return;
          }
          fileList.value.push({
            id: file.id,
            src: src,
            name: file.name,
            size: size,
            progress: file.processed,
            errorCode: 0,
            errorMsg: "",
          });
        },
        118,
        118
      );
    });
    //立即触发上传
    _uploader.upload();
  });

  //上传前触发
  _uploader.on("uploadBeforeSend", function (obj: any, data: any, headers: any) {
    data.dirName = directorySelectedKeys.value[0];
    headers["Authorization"] = UserContext.getToken();
  });

  //上传过程中触发，携带上传进度。
  _uploader.on("uploadProgress", function (file: any, percentage: any) {
    let progress = percentage * 100;
    if (progress >= 100) {
      progress = 100;
    }
    fileList.value.find((f) => f.id == file.id).progress = progress;
  });

  // 上传错误
  _uploader.on("uploadError", function (file: any, reason: any) {
    let data = fileList.value.find((f) => f.id == file.id);
    data.errorMsg = "上传失败";
    data.errorCode = 2;
  });

  //
  //上传成功
  _uploader.on("uploadSuccess", function (file: any, response: any) {
    let data = fileList.value.find((f) => f.id == file.id);
    data.errorMsg = "上传成功";
    data.errorCode = 1;
    if (response.code == 0) {
      _onSuccess([response.data.url])
    }
  });

  //当validate不通过时以派送错误事件的形式通知调用者。通过
  _uploader.on("error", function (type: any) {
    let msg = "";
    switch (type) {
      case "Q_EXCEED_NUM_LIMIT":
        msg = "超出文件总数量";
        break;
      case "Q_EXCEED_SIZE_LIMIT":
        msg = "添加的文件过大";
        break;
      case "F_EXCEED_SIZE":
        msg = "添加的文件过大";
        break;
      case "Q_TYPE_DENIED":
        msg = "不支持该类型文件";
        break;
    }
    message.error(msg);
  });
};

//添加目录
const onAddDirSubmit = async () => {
  let rs = await FileManageService.createDirectoryAsync(dirName.value);
  if (rs.code == 0) {
    dirVisible.value = false;
    getDirectory();
    message.success("创建成功");
  } else {
    message.error("创建失败");
  }
};

//*************在线管理***************
const onlineImgs = ref<any[]>([]);
const nextMarker = ref();
const directorySelectedKeys = ref<string[]>(["1"]);
const onLoadFile = async (marker: string, dirName: string) => {

  let rs = await FileManageService.fileListAsync(marker, dirName);

  rs.url.forEach((item: any) => {
    onlineImgs.value.push({
      url: item,
      selected: false,
    })
  });

  nextMarker.value = rs.nextMarker;
};

//加载更多图片
const onLoadMoreFile = () => {
  onLoadFile(nextMarker.value, directorySelectedKeys.value[0]);
};

//获取目录
async function getDirectory() {
  directory.value = await FileManageService.directoryListAsync();
}

//目录选中
const onDirSelect = (item: any) => {
  onlineImgs.value = [];
  selectedImage.value = 0;
  selectedImages = [];
  onLoadFile("", item.key);
};

//tabs切换
const tabsActiveKey = ref(1);
const onTabsChange = (key: number) => {
  if (key == 1) {
    return;
  }
  //切换到图片管理 清理原数据
  onlineImgs.value = [];
  let dir = directorySelectedKeys.value[0];
  onLoadFile(nextMarker.value, dir);
};

//在线图片选中
const selectedImage = ref(0);
let selectedImages: any[] = [];

const onImageSelected = (index: number, url: string) => {
  let _this = onlineImgs.value[index];
  let ck = _this.selected;
  if (ck) {
    ck = false;
    selectedImage.value--;
  } else {
    ck = true;
  }

  if (ck) {
    var count = selectedImage.value; //onlineImgs.value.filter(f => f.selected).length;
    if (count >= props.fileNum) {
      message.warn("已超过限制数量");
      return;
    }
    selectedImage.value++;
  }
  _this.selected = ck;
  selectedImages.push(url);
};

//调用目录
if (props.online) {
  getDirectory();
}




//关闭
const onCancel = () => {
  modalVisible.value = false;
  _uploader = null;
};

//成功回调
const _onSuccess = (url: any[]) => {
  //typeof props.onSuccess === 'function' && props.onSuccess(url);
  props.onSuccess?.(url)
  onCancel();
}

//确定选中
const onSelected = () => {
  _onSuccess(selectedImages);
};

//完全关闭 动画完成后
const afterClose = () => {
  props.onEnd?.();
  // typeof props.onEnd === 'function' && props.onEnd();
}



</script>

<style scoped>
.file-upload {
  width: 760px;
  min-height: 600px;
  margin: auto;
  border: 1px solid #f3f3f3;
}

.file-upload-dire-menu {
  background: #f7f7f7;
}

.file-upload-dire-menu .ant-menu-item-selected {
  background-color: #fff !important;
}

.file-upload-content {
  padding: 0px 0 0 10px;
  background-color: #fff;
  height: 100%;
}

.file-upload-content>h4 {
  padding: 20px 0 0 15px;
}

.file-upload-header {
  background-color: #f0f2f5;
}

.file-upload-upload-item {
  display: inline-block;
  width: 120px;
  height: 120px;
  margin: 6px;
  position: relative;
}

.upload-btn {
  position: relative;
  line-height: 30px;
  width: 97px;
  top: -5px;
}

.file-upload-upload-btn:hover {
  border-color: #1890ff;
  color: #1890ff;
}

.file-upload-upload-item-size {
  position: absolute;
  bottom: 10px;
  left: 4px;
  display: block;
  padding: 0 5px;
  line-height: 18px;
  color: #fff;
  background-color: #808080;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 9px;
  font-size: 12px;
  transition: opacity 0.4s;
}

.file-upload-upload-item-status {
  position: absolute;
  top: -2px;
  right: 2px;
  color: #52c41a;
}

.file-upload-upload-item-progress {
  position: absolute;
  width: 100%;
  bottom: -6px;
}

.file-upload-upload-item img {
  width: 118px;
  height: 118px;
}

.file-upload-upload-item-name {
  width: 120px;
  font-size: 13px;
  padding-top: 3px;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

.file-upload-footer {
  background-color: #fff;
  border-top: 2px solid #f3f3f3;
  padding: 15px 15px 15px 20px;
  text-align: right;
}

.file-upload-footer-tip {
  display: inline-block;
  padding: right 10px;
}

.file-upload-add {
  padding: 20px;
  text-align: center;
}

.file-upload-file-wap {
  height: 500px;
  padding-bottom: 10px;
  overflow: auto;
}

.file-upload-upload-wap {
  display: flex;
  flex-wrap: wrap;
}

.file-upload-online-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.file-upload-online-list>li {
  display: inline-block;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  width: 120px;
  height: 120px;
  overflow: hidden;
  position: relative;
  margin: 6px;
}

.file-upload-online-list>li:hover {
  border-color: red;
}

.file-upload-online-list-img-selected {
  position: absolute;
  content: "";
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  z-index: 1;
  background-color: rgba(0, 0, 0, 0.8);
  text-align: center;
  color: #fff;
  font-size: 20px;
  font-weight: bold;
  line-height: 120px;
  border: 3px solid #fff;
}

.file-upload-online-list>li img {
  display: inline-block;
  height: 100% !important;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.file-upload-online-btn {
  padding: 0px 7px;
}
</style>